package com.joy.web.admin.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.joy.web.admin.mapper.UserMapper;
import com.joy.web.admin.service.IUserBaseInfoService;
import com.joy.web.admin.service.IUserRoleService;
import com.joy.web.admin.service.IUserService;
import com.joy.common.constant.CommonCons;
import com.joy.common.model.vo.UserInfoVO;
import com.joy.web.admin.entity.User;
import com.joy.web.admin.entity.UserBaseInfo;
import com.joy.web.admin.entity.UserRole;
import com.joy.web.base.service.impl.IBaseServiceImpl;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author yjzhao
 * @since 2019-09-09
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl extends IBaseServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private IUserBaseInfoService userBaseInfoService;
    @Resource
    private IUserRoleService userRoleService;

    @Resource(name = "shiroCacheManager")
    private CacheManager shiroCacheManager;

    @Override
    public IPage<UserInfoVO> getUserInfoList(UserInfoVO userInfoVO, Page<UserInfoVO> page) throws Exception {
        return page.setRecords(baseMapper.getUserInfoList(userInfoVO, page)) ;
    }

    @Override
    public UserInfoVO findUserInfoByUserId(String userId) throws Exception {
        //根据 userId 获取用户信息
        User user = this.getById(userId);
        QueryWrapper<UserBaseInfo> qWrapper = new QueryWrapper<>();
        qWrapper.lambda().eq(UserBaseInfo::getUserId, userId).eq(UserBaseInfo::getDelYn, CommonCons.FlagType.N);
        UserBaseInfo userInfo = userBaseInfoService.getOne(qWrapper);
        UserInfoVO userInfoVO = userInfo.convert(UserInfoVO.class);
        userInfoVO.setUserNm(user.getUserNm());
        return userInfoVO;
    }

    @Override
    @Transactional(readOnly = false)
    public boolean updateUserBaseInfoAndRoles(UserInfoVO userInfoVO) throws Exception {
        boolean updateFlag = updateUserBaseInfo(userInfoVO);
        //更新角色
        //1. 刪除原來角色
        userRoleService.lambdaUpdate().set(UserRole::getDelYn, CommonCons.FlagType.Y)
                .eq(UserRole::getDelYn, CommonCons.FlagType.N)
                .eq(UserRole::getUserId, userInfoVO.getUserId())
                .update();
        //2. 新增新角色
        List<String> roleIdList = userInfoVO.getRoleIdList();
        if (!CollectionUtils.isEmpty(roleIdList)) {
            roleIdList.forEach(roleId ->{
                UserRole userRole = new UserRole();
                userRole.setRoleId(roleId);
                userRole.setUserId(userInfoVO.getUserId());
                userRoleService.save(userRole);
            });
        }

        return updateFlag;
    }

    @Override
    @Cacheable(value= CommonCons.MyCache.USERINFOS, key="#userNm")
    public UserInfoVO findUserInfoByUserNm(String userNm) throws Exception {
        //根据 userId 获取用户信息
        QueryWrapper<User> qWrapper = new QueryWrapper<>();
        qWrapper.lambda().eq(User::getUserNm, userNm).eq(User::getDelYn, CommonCons.FlagType.N);
        User user = this.getOne(qWrapper);
        if (user == null || StrUtil.isEmpty(user.getId())) {
            return null;
        }
        UserBaseInfo userBaseInfo = userBaseInfoService
                .getOne(new QueryWrapper<UserBaseInfo>().eq("user_id", user.getId()));
        UserInfoVO userInfoVO = userBaseInfo.convert(UserInfoVO.class);
        userInfoVO.setUserNm(user.getUserNm());
        return userInfoVO;

    }

    @Override
    @CacheEvict(value= CommonCons.MyCache.PERMISSIONS, allEntries = true)
    public void removeUserAuthorization() {
        Cache<SimplePrincipalCollection, Object> cache = shiroCacheManager.getCache("authorizationCache");
        if (cache != null) {
            cache.clear();
        }

    }

    @Override
    @Transactional(readOnly = false)
    public boolean resetPwd(String userId) throws Exception {
        //初始密码加密
        String pwd = CommonCons.INIT_USER_VAL.PWD;
        //更改密码
        return updatePwd(userId, pwd);
    }

    @Override
    @Transactional(readOnly = false)
    public boolean updatePwd(String userId, String newPwd) {
        //更改密码
        boolean updateFlag = this.lambdaUpdate().set(User::getUserPwd, SecureUtil.md5().digestHex(newPwd).toUpperCase())
                .eq(User::getDelYn, CommonCons.FlagType.N)
                .eq(User::getId, userId)
                .update();

        return updateFlag;
    }

    @Override
    @Transactional(readOnly = false)
    @CacheEvict(value= CommonCons.MyCache.USERINFOS, key="#userInfoVO.userNm", condition = "#userInfoVO != null && #userInfoVO.userNm != null")
    public boolean updateUserBaseInfo(UserInfoVO userInfoVO) {
        boolean updateFlag = userBaseInfoService.lambdaUpdate()
                .set(StrUtil.isNotEmpty(userInfoVO.getUserRealNm()),
                        UserBaseInfo::getUserRealNm, userInfoVO.getUserRealNm())
                .set(StrUtil.isNotEmpty(userInfoVO.getEmail()),
                        UserBaseInfo::getEmail, userInfoVO.getEmail())
                .set(StrUtil.isNotEmpty(userInfoVO.getMobileNo()),
                        UserBaseInfo::getMobileNo, userInfoVO.getMobileNo())
                .set(StrUtil.isNotEmpty(userInfoVO.getPortraitFileId()),
                        UserBaseInfo::getPortraitFileId, userInfoVO.getPortraitFileId())
                .set(StrUtil.isNotEmpty(userInfoVO.getPortraitShowUri()),
                        UserBaseInfo::getPortraitShowUri, userInfoVO.getPortraitShowUri())
                .eq(UserBaseInfo::getUserId, userInfoVO.getUserId())
                .eq(UserBaseInfo::getDelYn, CommonCons.FlagType.N)
                .update();
        return updateFlag;
    }
}
